package com.hs.websocket;

import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.hs.entity.pojo.Dialogue;
import com.hs.entity.pojo.Message;
import com.hs.service.DialogueService;
import com.hs.utils.ResultResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@ServerEndpoint(value = "/ws/{dialogueId}/{userId}")
public class Websocket {
    /**
     * 记录在线连接
     */
    public static final Map<String, WebSocketData> sessionMap = new ConcurrentHashMap<>();

    /**
     * 封装一个sessionData的类，内含通讯标识和session对象
     */
    private final WebSocketData webSocketData = new WebSocketData();

    private static DialogueService dialogueService;

    @Autowired
    public void setDialogueService(DialogueService service) {
        Websocket.dialogueService = service;
    }

    //获取当前在线人数
    private static synchronized int getOnlineCount() {
        return sessionMap.size();
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId, @PathParam("dialogueId") String dialogueId) {
        webSocketData.setSession(session);
        webSocketData.setDialogueId(dialogueId);
        sessionMap.put(userId, webSocketData);
        log.info("{}: 开始创建连接，新用户{}加入，当前在线人数{}", session, userId, getOnlineCount());
    }

    @OnMessage
    public void onMessage(String message, @PathParam("userId") String userId, @PathParam("dialogueId") String dialogueId) {
        WebSocketData senderWebSocketData = sessionMap.get(userId);
        // 判断发送者连接
        if (senderWebSocketData.getSession() != null) {
            log.info("收到的消息为{}", message);
            // 数据处理
            Message m = new Message();
            // TODO 封装Message
            Integer dId = Integer.valueOf(dialogueId);
            Integer uId = Integer.valueOf(userId);
            m.setDialogueId(dId);
            m.setCreateTime(new Date());
            m.setUserId(uId);
            m.setContent(message);
            // 接收者id
            Dialogue dialogue = dialogueService.getById(dId);
            Integer messageReceiver = dialogue.getTheOneUserId().equals(uId) ? dialogue.getTheOtherUserId() : dialogue.getTheOneUserId();
            m.setMessageReceiver(messageReceiver);

            log.info("转换成message实体为{}", m);
            try {
                // 发送消息
                sendMessage(senderWebSocketData, m);
            } catch (IOException e) {
                log.warn("发送失败，传输出现问题", e);
            }
        } else {
            log.info("发送失败，未找到用户userId={}的session", userId);
        }
    }

    private static final JSONConfig jsonConfig = JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss");

    private void sendMessage(WebSocketData senderWebSocketData, Message message) throws IOException {
        Session senderSession = senderWebSocketData.getSession();
        if (message == null) {
            // 数据异常，提醒发送者
            senderSession.getBasicRemote().sendText(JSONUtil.toJsonStr(ResultResponse.fail("数据异常！")));
        } else {

            // 尝试获取接收者连接
            WebSocketData receiverWebSocketData = sessionMap.get(message.getMessageReceiver().toString());
            // 接收者处于在线状态
            if (Objects.nonNull(receiverWebSocketData) && Objects.nonNull(receiverWebSocketData.getSession())) {
                // 判断当前连接是否为当前通话创建的连接，设置消息为已读
                if (receiverWebSocketData.getDialogueId().equals(senderWebSocketData.getDialogueId())) {
                    message.setMessageReadFlag(true);
                }
                // 给接收者发送
                receiverWebSocketData.getSession().getBasicRemote().sendText(JSONUtil.toJsonStr(message, jsonConfig));
            }
            // 给发送者发送
            senderSession.getBasicRemote().sendText(JSONUtil.toJsonStr(message, jsonConfig));
        }

    }


    /**
     * @description 连接关闭调用的方法
     * @method onClose
     * @date 2022/9/25 23:10
     **/
    @OnClose
    public void onClose(@PathParam("userId") String userId) {
        sessionMap.remove(userId);
        log.info("用户{}连接断开，在线用户{}人……", userId, getOnlineCount());
    }
}